/**
 * @author Andrew Dashin <dashin@andrewdashin.com>
 */

var MYSQL_ENGINES = ['MyISAM', 'MEMORY', 'InnoDB', 'ARCHIVE', 'MRG_MYISAM'];
var MYSQL_TYPES   = ['BIT', 'TINYINT', 'BOOL', 'SMALLINT', 'MEDIUMINT', 'INT',
                     'BIGINT', 'FLOAT', 'DOUBLE', 'DECIMAL', 'DATE', 'DATETIME',
                     'TIMESTAMP', 'TIME', 'YEAR', 'CHAR', 'VARCHAR', /*17*/'BINARY',
                     'VARBINARY', 'TINYBLOB', 'TINYTEXT', 'BLOB', 'TEXT',
                     'MEDIUMBLOB', 'MEDIUMTEXT', 'LONGBLOB', 'LONGTEXT'/*, 'ENUM',
                     'SET'*/];
var UNSIGNED_ZEROFILL = {1:'', 3:'', 4:'', 5:'', 6:'', 7:'', 8:'', 9:''};
var LENGTH   = {1:'', 3:'', 4:'', 5:'', 6:'',  15:'', 16:'', 17:'', 18:'', 21:'', 22:''};
var DOUBLE_LENGTH = {7:'', 8:'', 9:''};

// + SET, ENUM
// + FLOAT, DOUBLE, DECIMAL
// + YEAR

//TINYINT[(M)] [UNSIGNED] [ZEROFILL]
//SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
//-32768 to 32767. The unsigned range is 0 to 65535.

//MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
//-8388608 to 8388607. The unsigned range is 0 to 16777215.

//INT[(M)] [UNSIGNED] [ZEROFILL] -- INTEGER (synonym)
//-2147483648 to 2147483647. The unsigned range is 0 to 4294967295.

//BIGINT[(M)] [UNSIGNED] [ZEROFILL]
//-9223372036854775808 to 9223372036854775807. The unsigned range is 0 to 18446744073709551615.

//FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
//-3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to 3.402823466E+38.

//DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
//-1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to 1.7976931348623157E+308.

//TODO DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]
//TODO FLOAT(p) [UNSIGNED] [ZEROFILL]

//DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
//

//DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
//These types are synonyms for DECIMAL. The FIXED synonym was added in MySQL 4.1.0 for compatibility with other database systems. 

//MEDIUMBLOB  
//A BLOB column with a maximum length of 16,777,215 (224 – 1) bytes.

//MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]
//A TEXT column with a maximum length of 16,777,215 (224 – 1) characters.

//LONGBLOB  
//A BLOB column with a maximum length of 4,294,967,295 or 4GB (232 – 1) bytes. Up to MySQL 3.23, the client/server protocol and MyISAM tables had a limit of 16MB per communication packet or table row. From MySQL 4.0, the maximum allowed length of LONGBLOB  columns depends on the configured maximum packet size in the client/server protocol and available memory.

//LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]
//A TEXT column with a maximum length of 4,294,967,295 or 4GB (232 – 1) characters. Up to MySQL 3.23, the client/server protocol and MyISAM tables had a limit of 16MB per communication packet or table row. From MySQL 4.0, the maximum allowed length of LONGTEXT  columns depends on the configured maximum packet size in the client/server protocol and available memory.

//ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]
//An enumeration. A string object that can have only one value, chosen from the list of values 'value1', 'value2', ..., NULL or the special '' error value. An ENUM column can have a maximum of 65,535 distinct values. ENUM values are represented internally as integers.

//SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]
//A set. A string object that can have zero or more values, each of which must be chosen from the list of values 'value1', 'value2', ... A SET column can have a maximum of 64 members. SET values are represented internally as integers.

//CHAR [CHARACTER SET charset_name] [COLLATE collation_name]
//synonym for CHAR(1)

//[NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name] 
//The range of M is 1 to 255 before MySQL 4.0.2, and 0 to 255 as of MySQL 4.0.2.

//BINARY(M)
//The BINARY type is similar to the CHAR type, but stores binary byte strings rather than non-binary character strings.

//VARBINARY(M)
//The VARBINARY type is similar to the VARCHAR type, but stores binary byte strings rather than non-binary character strings. 

//TINYBLOB  
//A BLOB column with a maximum length of 255 (28 – 1) bytes.

//TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]
//A TEXT column with a maximum length of 255 (28 – 1) characters.

//BLOB[(M)]
//A BLOB column with a maximum length of 65,535 (216 – 1) bytes.
//Beginning with MySQL 4.1, an optional length M can be given for this type. MySQL creates the column as the smallest BLOB type large enough to hold values M bytes long.

//TEXT[(M)] [CHARACTER SET charset_name] [COLLATE collation_name]
//A TEXT column with a maximum length of 65,535 (216 – 1) characters.


//DATETIME  
//'YYYY-MM-DD HH:MM:SS'

//DATE
//'YYYY-MM-DD'

//TIMESTAMP[(M)]
//'0000-00-00 00:00:00'

//TIME  
//'HH:MM:SS' 

//YEAR[(2|4)]
//A year in two-digit or four-digit format. The default is four-digit format. In four-digit format, the allowable values are 1901 to 2155, and 0000. In two-digit format, the allowable values are 70 to 69,


// BOOL synonym BOOLEAN

var MyTypes = Class.create();
MyTypes.prototype = {
	initialize: function () {
		//
	},
    isTypeInt: function (nType) {
        return typeof(MYSQL_INT_TYPES[nType]) == 'undefined' ? false : true;
    },
    isTypeFloat: function (nType) {
        return typeof(MYSQL_FLOAT_TYPES[nType]) == 'undefined' ? false : true;
    },
    getType: function (nType) {
        
    }
};
var MyMenuBar = Class.create();
MyMenuBar.prototype = Object.extend(new JTKWidget(), {
	initialize: function () {
		this.setClass('MyMenuBar');
		this.setId('menuBar');
	}
});

var MyLayout = Class.create();
MyLayout.prototype = Object.extend(new JTKWidgetContainer(), {
	initialize: function() {
		this.setClass('MyLayout');
		this.setId('mainPane');
	},
	
    /**
    * @method
    * @description
    */ 
	resize: function() {
//        var menu = document.getElementById('menuBar');
        var side = document.getElementById('sideBar');
        var main = document.getElementById('myPane');
           main.style.width = document.body.clientWidth - main.offsetLeft;
           main.style.height = document.body.clientHeight - main.offsetTop;
           side.style.height = document.body.clientHeight - side.offsetTop;
//           menu.innerHTML = "Width: " + document.body.clientWidth + " Height: " + document.body.clientHeight + " wdth: " + main.style.width;
	}
});

var MyPane = Class.create();
MyPane.prototype = Object.extend(new JTKWidgetContainer(), {
	initialize: function() {
		this.setClass('MyPane');
		this.setId('myPane');
	}
});


var MySideBar = Class.create();
MySideBar.prototype = Object.extend(new JTKWidget(), {
	initialize: function () {
		this.setClass('MySideBar');
		//this.div.className = 'MySideBar';
		this.div.id = 'sideBar';
	}
});


var MyWireArrow = Class.create();
MyWireArrow.prototype = Object.extend(new JTKArrow(), {
	initialize: function (isLeft) {
		JTKArrow.prototype.initialize.call(this);
    	this.setClass('MyWireArrow');
		if(isLeft) {
			this.setImage('img/updir.png');
		} else {
			this.setImage('img/rarrow.gif');
		}
	}
});

var MySlot = Class.create();
MySlot.prototype = Object.extend(new JTKConnectionSlot(), {
	initialize: function (connectionObject) {
		this.connectionObject = connectionObject;
	},
	
    /**
    * @method
    * @description
    */ 
	getFieldOutPoint: function () {
		return new JTKPoint(this.connectionObject.div.offsetLeft + 250 + 3 + this.connectionObject.div.style.borderWidth*2, this.connectionObject.div.offsetTop + 44);
	},
	
    /**
    * @method
    * @description
    */ 
	getFieldInPoint: function () {
		return new JTKPoint(this.connectionObject.div.offsetLeft - 3, this.connectionObject.div.offsetTop + 44);
	}
});

var MySqlField = Class.create();
MySqlField.prototype = Object.extend(new JTKWidget(), {
	initialize: function () {
		
	},
	
    /**
    * @method
    * @description
    */ 
	setType: function () {
		
	}
});

var MyEngineInput = Class.create();
MyEngineInput.prototype = Object.extend(new JTKSelectBox(), {
    initialize: function (nSelected) {
        JTKSelectBox.prototype.initialize.call(this);
        this.loadArray(MYSQL_ENGINES);
        if (typeof nSelected != 'undefined') {
            this.select.options[nSelected].selected = true;
        }
    }
});

var MyPrimaryKeyInput = Class.create();
MyPrimaryKeyInput.prototype = Object.extend(new JTKSelectBox(), {
	initialize: function (oEditor) {
        JTKSelectBox.prototype.initialize.call(this);
		this.setClass("MyEditorPrimaryKeyInput");
		this.editor = oEditor;
		this.loadFields();
		var oThis = this;
		this.select.onchange = function () {
			oEditor.setPrimaryKey(oThis.select.options[oThis.getSelectedIndex()].text);
		};
	},
	loadFields: function () {
		// Clear all
		this.select.options.length = 0;
		var aFields = this.editor.getEntity().getFieldsSet().getFields();
		this.addOption("", "");
		for(var i = aFields.length - 1; i >= 0; i--) {
			this.addOption(aFields[i].name, i);
			if (this.editor.getEntity().primaryKey == aFields[i].name) {
				this.select.options[(i - 1) > 0 ? (i-1) : 0].selected = true;
			}
		}
	}
});

var MyTypeInput = Class.create();
MyTypeInput.prototype = Object.extend(new JTKSelectBox(), {
    initialize: function (nSelected) {
        JTKSelectBox.prototype.initialize.call(this);
        
        this.loadArray(MYSQL_TYPES);
        if (typeof nSelected != 'undefined') {
            this.select.options[nSelected].selected = true;
        }
    }
});

var MyTypePropsInput = Class.create();
MyTypePropsInput.prototype = Object.extend(new JTKWidget(), {
        field: null,
		length: null,
		unsigned: null,
		zerofill: null,
		notnull: false,
        initialize: function (oEditor, oField) {
			this.editor = oEditor;
            var oThis = this;
			this.setClass('MyTypePropsInput');
            this.field = oField;
            var oName = document.createElement('input');
            this.name = oName;
			this.name.title = i18n("mypropsinput.labels.fieldname.text");
            this.name.type = 'text';
            this.name.value = oField.getName();
            this.name.onchange = function () {
				if (oName.value.length > 0) {
	                oField.updateName(oName.value);
				} else {
					alert(i18n("mypropsinput.labels.fieldname.fieldemptyalert"));
				}
            }
			var oType = new JTKWidget();
			this.type = oType;
			oType.type = new MyTypeInput(oField.getType());
			oType.div.appendChild(oType.type.div);
            oType.type.select.onchange = function () {
 				oThis.onChange();
            };
            this.div.appendChild(this.name);
			this.div.appendChild(this.type.div);
			
			this.notnull = document.createElement('input');
			this.notnull.type = 'checkbox';
			this.notnull.title = i18n("mypropsinput.notnull.title.text");

			this.notnull.checked = oField.notnull;
			this.notnull.onchange = function () {
				oField.updateNotnull(oThis.notnull.checked);
			};
			this.div.appendChild(this.notnull);
			
            oThis.onChange();
            this.deleteLink = document.createElement('img');
            this.deleteLink.src = 'img/delete.gif';
            this.deleteLink.onclick = function () {
                oField.destroy();
                oThis.div.parentNode.removeChild(oThis.div);
                oThis.editor.reload();
            };
            this.div.appendChild(this.deleteLink);
        },
        update: function () {
            this.field.update(this.name.value, this.type.type.select.value);
        },
		onChange: function () {
			var oField = this.field;
			var oType = this.type;
			var oThis = this;
            oField.updateType(oType.type.select.value);
			
			oField.updateNotnull(oThis.notnull.checked);
			if (oThis.length != null) {
				oThis.type.div.removeChild(oThis.length);
				oThis.length = null;
				oField.updateLength(null);
			}
			if (oThis.unsigned != null) {
				oThis.type.div.removeChild(oThis.unsigned);
				oThis.unsigned = null;
				oField.updateUnsigned(null);
				oThis.type.div.removeChild(oThis.zerofill);
				oThis.zerofill = null;
				oField.updateZerofill(null);
			}
			
			if (typeof(LENGTH[oType.type.select.value]) != 'undefined') {
				oThis.length = document.createElement('input');
				oThis.length.title = i18n("mypropsinput.length.title.text");
				oThis.length.type = 'text';
				oThis.length.className = 'MyTypePropsInputLength';
				oThis.length.value = oField.getLength() == null ? 1 : oField.getLength();
				oThis.type.div.appendChild(oThis.length);
				oField.updateLength(oThis.length.value);
				oThis.length.onchange = function () {
					oField.updateLength(oThis.length.value);
				};
				if (typeof(UNSIGNED_ZEROFILL[oType.type.select.value]) != 'undefined') {
					oThis.unsigned = document.createElement('input');
					oThis.unsigned.title = i18n("mypropsinput.unsigned.title.text");
					oThis.unsigned.type = 'checkbox';
					oThis.type.div.appendChild(oThis.unsigned);
					oThis.unsigned.checked = oField.getUnsigned() == null ? false : oField.getUnsigned();
					oField.updateUnsigned(oThis.unsigned.checked);
					oThis.unsigned.onchange = function () {
						oField.updateUnsigned(oThis.unsigned.checked);
					};
					
					oThis.zerofill = document.createElement('input');
					oThis.zerofill.title = i18n("mypropsinput.zerofill.title.text");
					oThis.zerofill.type = 'checkbox';
					oThis.type.div.appendChild(oThis.zerofill);
					oThis.zerofill.checked = oField.getZerofill() == null ? false : oField.getZerofill();
					oField.updateZerofill(oThis.zerofill.checked);
					oThis.zerofill.onchange = function () {
						oField.updateZerofill(oThis.zerofill.checked);
					};
				}
			}
            oThis.editor.reload();
		}
});

var MyEntityEditor = Class.create();
MyEntityEditor.prototype = Object.extend(new JTKWindow(), {
		active: false,
        entity: null,
        initialize: function (oEntity) {
            //
			MyEntityEditor.prototype.active = true;
            this.fields = new Array();
            this.entity = oEntity;
            // not used yet
            //this.changed = false;
            var oBar = new JTKDraggableBar(i18n("myentityeditor.title.text"));
                oBar.setClass('MyDraggableBar');
            oBar.show(this);
			
			var oPane = new JTKWidget();
			oPane.setClass('MyEntityEditorPane');
			
			this.div.appendChild(oPane.div);
			
            this.setClass('MyEntityEditor');
            JTKLock.prototype.lockClass.call(this, 'MyEntity');
            
			var oEntityNameLabel = new JTKWidget();
			oEntityNameLabel.setClass('MyEntityEditorLabel');
			oEntityNameLabel.div.innerHTML = i18n("myentityeditor.labels.entityname.text");
			oEntityNameLabel.show(oPane);

            var tableName  = document.createElement('input');
			var oThis = this;
			var oPK = new MyPrimaryKeyInput(oThis);
			this.primaryKey = oPK;
            this.tableName = tableName;
            this.tableName.type = 'text';
            this.tableName.value = oEntity.getName();
            this.tableName.onchange = function () {
				if (oThis.checkEntityName(tableName.value)) {
                	oEntity.setName(tableName.value);
				}
            }
            oPane.div.appendChild(this.tableName);
            
			var oFieldsLabel = new JTKWidget();
			oFieldsLabel.setClass('MyEntityEditorLabel');
			oFieldsLabel.div.innerHTML = i18n("myentityeditor.labels.fields.text");
			oFieldsLabel.show(oPane);
            var fieldsContainer = new JTKWidget();
            for (var i = 0; i < oEntity.fieldsSet.fields.length; i++) {
                var oFieldInput = new MyTypePropsInput(this, oEntity.fieldsSet.fields[i]);
                fieldsContainer.div.appendChild(oFieldInput.div);
                this.fields.push(oFieldInput);
            }
            oPane.div.appendChild(fieldsContainer.div);
            
            // create "add field" control
			var oAddFieldLabel = new JTKWidget();
			oAddFieldLabel.setClass('MyEntityEditorLabel');
			oAddFieldLabel.div.innerHTML = i18n("myentityeditor.labels.addfield.text");
			oAddFieldLabel.show(oPane);
            var newField = new MyTypePropsInput(this, new MyEntityField('', 0));
            newField.name.onchange = function () {};
            newField.type.type.select.onchange = function () {
				newField.onChange();
			};
			newField.deleteLink.src = 'img/save.gif';
            newField.deleteLink.onclick = function () {
				if (newField.name.value.length > 0) {
					var oOpts = {};
					oOpts.length = newField.length == null ? null : newField.length.value;
					oOpts.unsigned = newField.unsigned == null ? null : newField.unsigned.checked;
					oOpts.zerofill = newField.zerofill == null ? null : newField.zerofill.checked;
					oOpts.notnull  = newField.notnull.checked;
	                var property = new MyTypePropsInput(oThis, oEntity.fieldsSet.addField(newField.name.value, newField.type.type.select.value, oOpts));
	                fieldsContainer.div.appendChild(property.div);
	                newField.name.value = "";
	                newField.type.type.select.value = 0;
					oPane.scrollBottom();
				} else {
					alert(i18n("myentityeditor.alerts.emptyfield.text"));
				}
				oThis.reload();
            };
            oPane.div.appendChild(newField.div);

		var oCloseImg = new JTKImg();
			oCloseImg.setImage('img/close.gif');
            oCloseImg.setClass("MyEntityCloseButton");
			oCloseImg.show(oBar);
            var oEditor = this;
            oCloseImg.setOnClick(function () {
				// This if statement always returns true
				// so soon we could delete it
                if (!oEditor.changed || confirm("Do not save changes?")) {
                    JTKLock.prototype.unLockClass.call(this, 'MyEntity');
					MyEntityEditor.prototype.active = false;
                    oEditor.dispose();
                }
            });

			// Primary keys
			var oPKLabel = new JTKWidget();
			oPKLabel.setClass('MyEntityEditorLabel');
			oPKLabel.div.innerHTML = i18n("myentityeditor.labels.primarykey.text");
			oPKLabel.show(oPane);			
			//oPane.div.appendChild(oPK.div);
			oPK.show(oPane);
			// end primary keys
			
			var oEngineLabel = new JTKWidget();
			oEngineLabel.setClass('MyEntityEditorLabel');
			oEngineLabel.div.innerHTML = i18n("myentityeditor.labels.enginetype.text");
			oEngineLabel.show(oPane);
			
            var oSB = new MyEngineInput(oEntity.getEngine());

            oSB.select.onchange = function () {
                //oEditor.changed = true;
                oEntity.setEngine(oSB.getSelectedIndex());
            }
            oSB.setClass("MyEditorEngineInput");
            this.engine = oSB;//new MyTypePropsInput(oEntity.fieldsSet.fields[i]);
            oPane.div.appendChild(oSB.div);

			var FK = new JTKSelectBox();
			for (var i = 0; i < MyEntity.prototype.entities.length; i++) {
				if (MyEntity.prototype.entities[i] != null) 
					FK.addOption(MyEntity.prototype.entities[i].name, i);
			};
			FK.select.onchange = function () {
				oEntity.wireWith(MyEntity.prototype.entities[FK.getSelectedIndex()]);
			};
			oPane.div.appendChild(FK.select);
			this.setVisibility(false);
            this.show($('pane'));
            this.setPosition(new JTKPoint(Math.round((document.body.clientWidth / 2) - (this.div.clientWidth / 2)), 20));
			this.setVisibility(true);
			
        },
		getEntity: function () {
			return this.entity;
		},
		reload: function () {
			this.primaryKey.loadFields();
		},
		checkEntityName: function (sName) {
			if (sName == 0) {
				alert(i18n("myentityeditor.alerts.entityemptyname.text"));
				return false;
			}
			if (document.getElementById(sName)
			&& document.getElementById(sName).className == 'MyEntity') {
				alert(i18n("myentityeditor.alerts.enityexists.text"));
				return false;
			}
			return true;
		},
		
		setPrimaryKey: function (sFieldName) {
			this.entity.setPrimeryKey(sFieldName);
		},
		
        setEngine: function (i) {
        },
        
        cancel: function () {
        }
});

var MyEntityDraggableBar = Class.create();
MyEntityDraggableBar.prototype = Object.extend(new JTKDraggableBar(), {
	collapsed: false,
	/*
	 * This is constructor of About Box;
	 * @constructor
	 */
    initialize: function (sName, oEntity) {
        JTKDraggableBar.prototype.initialize.call(this, sName);
		var oThis = this;
		var oCollapseButton = new JTKWidget();
			oCollapseButton.setClass('MyEntityCollapseButton');
			oCollapseButton.setInnerHTML('V');
			oCollapseButton.show(this);
			oCollapseButton.div.onclick = function () {
				if (!oThis.collapsed) {
					oEntity.collapse();
					oCollapseButton.setInnerHTML('>');
					oThis.collapsed = true;
				} else {
					oEntity.expand();
					oCollapseButton.setInnerHTML('V');
					oThis.collapsed = false;
				}
			};
        var oImg = new JTKImg();
            oImg.setImage('img/edit.gif');
            oImg.setClass("MyEntityEditButton");
            oImg.setOnClick(function () {new MyEntityEditor(oEntity);});
            oImg.show(this);
		var oCloseImg = new JTKImg();
			oCloseImg.setImage('img/close.gif');
            oCloseImg.setClass("MyEntityCloseButton");
			oCloseImg.setOnClick(function () {
				oEntity.dispose();
			});
			oCloseImg.show(this);
    }
});

var MyEntityField = Class.create();
MyEntityField.prototype = Object.extend({}, {
		length: null,
		unsigned: null,
		zerofill: null,
		notnull: false,
        initialize: function (sName, nType, oOpts) {
            this.container = null;
            this.div = new JTKLi(); // actually it is not a div, but li
            this.type = nType;
            this.name = sName;
			if (typeof(oOpts) != 'undefined') {
				this.length = oOpts.length;
				if (typeof(oOpts.unsigned) != 'undefined') {
					this.unsigned = oOpts.unsigned;
					this.zerofill = oOpts.zerofill;
				}
				this.notnull = oOpts.notnull;
			}
            this.typeDiv = new JTKWidget();
            //this.typeDiv.div.innerHTML = sName + " "  + MYSQL_TYPES[nType];
			this.showField();
            this.typeDiv.show(this.div);
        },
		showField: function () {
			var sLength = typeof(this.length) == 'undefined' || this.length == null ? '' : '(' + this.length + ') ';
			var sUnsigned = typeof(this.unsigned) == 'undefined' || this.unsigned == null? '' : (this.unsigned == true ? 'UNSIGNED ' : '');
			var sZerofill = typeof(this.zerofill) == 'undefined' || this.zerofill == null? '' : (this.zerofill == true ? 'ZEROFILL ' : '');
			var sNotnull  = this.notnull == true ? ' NOT NULL' : '';
			this.typeDiv.div.innerHTML = this.name + " " + MYSQL_TYPES[this.type] + sLength + sUnsigned + sZerofill + sNotnull;
		},
        getType: function () {
            return this.type;
        },
        getName: function () {
            return this.name;
        },
		getLength: function () {
			return this.length;
		},
		getUnsigned: function () {
			return this.unsigned;
		},
		getZerofill: function () {
			return this.zerofill;
		},
		getNotnull: function () {
			return this.notnull;
		},
        update: function (sNewName, nNewType) {
            this.name = sNewName;
            this.type = nNewType;            
			this.showField();
        },
        updateName: function (sNewName) {
            this.name = sNewName;
			this.showField();
        },
        updateType: function (nNewType) {
            this.type = nNewType;
			this.showField();
        },
		updateOpts: function (oOpts) {
			this.length = oOpts.length;
			this.unsigned = oOpts.unsigned;
			this.zerofill = oOpts.zerofill;
			this.notnull  = oOpts.notnull;
			this.showField();
		},
		updateLength: function (nLength) {
			this.length = nLength;
			this.showField();
		},
		updateUnsigned: function (bUnsigned) {
			this.unsigned = bUnsigned;
			this.showField();
		},
		updateZerofill: function (bZerofill) {
			this.zerofill = bZerofill;
			this.showField();
		},
		updateNotnull: function (bNotnull) {
			this.notnull = bNotnull;
			this.showField();
		},
        destroy: function () {
            this.container.removeField(this);
        },
		generateSQL: function () {
			var sSQL = '';
			sSQL = '`' + this.getName() + '` ' + MYSQL_TYPES[this.getType()];
			if (this.getLength() != null) {
				sSQL += '(' + this.getLength() + ')';
				if (this.getUnsigned() != null) {
					sSQL += this.getUnsigned() == true ? ' UNSIGNED' : '';
				}
				if (this.getZerofill() != null) {
					sSQL += this.getZerofill() == true ? ' ZEROFILL' : '';
				}
			}
			sSQL += this.getNotnull() ? ' NOT NULL': '';
			return sSQL;
		}
});

var MyEntityFieldSet = Class.create();
MyEntityFieldSet.prototype = Object.extend(new JTKWidget(), {
        initialize: function(oEntity) {
			this.entity = oEntity;
            this.div.ul = document.createElement('ul');
            this.div.appendChild(this.div.ul);
            this.fields = new Array();
			this.setClass('MyEntityFieldSet');
        },
        addField: function (sName, nType, oOpts) {
            var field;
			if (typeof(oOpts) == 'undefined') {
				field = new MyEntityField(sName, nType);
			} else {
				field = new MyEntityField(sName, nType, oOpts);
			}
            this.fields.push(field);
            this.div.ul.appendChild(field.div);
            field.container = this;
			this.entity.div.style.height = this.entity.div.clientHeight + 14 + 'px';
            return field;
        },
        getFields: function () {
            return this.fields;
        },
        removeField: function (oField) {
            this.fields.pop(oField);
            this.div.ul.removeChild(oField.div);
        }
});

var MyEntity = Class.create();
MyEntity.prototype = Object.extend(new JTKWireableWindow(), {
	entities: new Array(),
    counter: 0,
    engine: {},
    name: "",
	primaryKey: "",
	initialize: function (sName) {
        // init engine
		MyEntity.prototype.entities.push(this);
        this.engine  = Object.extend(new JTKWidget(), {initialize: function () {}, type: 0});
        if (typeof(sName) == 'undefined') {
            MyEntity.prototype.counter += 1;
            var sName = 'table' + MyEntity.prototype.counter;
        }
        this.name = sName;
		this.div.id = sName;
		var oBar = new MyEntityDraggableBar(sName, this);
        this.bar = oBar;
		oBar.setClass('MyDraggableBar');
		this.appendBar(oBar);
        
        this.fieldsSet = new MyEntityFieldSet(this);
        //
//        this.fieldsSet.addField('ID', 5, {length: 5, unsigned: true, zerofill: true, notnull: false});
        //
        this.fieldsSet.show(this.div);
		this.setClass('MyEntity');
        this.engine.div.innerHTML = MYSQL_ENGINES[this.engine.type];
		this.engine.setClass('MyEntityEngine');
        this.engine.show(this);
		// this hardcode should be removed later
		this.div.style.top  = 18 + MyEntity.prototype.counter * 4 + 'px';
		this.div.style.left = 190 + MyEntity.prototype.counter * 4 + 'px';
	},
	
	getFieldsSet: function () {
		return this.fieldsSet;
	},
	
	setPrimeryKey: function (sFieldName) {
		this.primaryKey = sFieldName;
		for( var i = 0; i < this.getFieldsSet().getFields().length; i++) {
			if (this.getFieldsSet().getFields()[i].name == sFieldName) {
				this.getFieldsSet().getFields()[i].div.className = "MyEntityKey";
			} else {
				this.getFieldsSet().getFields()[i].div.className = "";
			}
		}
	},
    
    setName: function (sName) {
		delete this.entities[this.getName()];
		this.entities[sName] = this;
        this.name = sName;
        this.bar.setTitle(sName);
    },
    
    getName: function () {
        return this.name;
    },
    
    setEngine: function (type) {
        if (typeof(type) != 'undefined') {
            //MYSQL_ENGINES[i]
            this.engine.type = type;
            this.engine.div.innerHTML = MYSQL_ENGINES[this.engine.type];
        }
    },
    
    getEngine: function () {
        return this.engine.type;
    },
	
    /**
    * @method
    * @description
    */ 
	wireWith: function (oOtherObj) {
		// Needs to make the connection
		// from appropriate points
		//
		var slotSrc = this.getNewSlot();
		var slotDst = oOtherObj.getNewSlot();
		var oWire = new JTKConnectionWire(slotSrc, slotDst, 'MyWire', this.getDisplayContext());
		oWire.getDstWire().setArrow(new MyWireArrow(true));
		this.redrawWires();
	},
	
    /**
    * @method
    * @description
    */ 
	getNewSlot: function () {
		var slot = new MySlot(this);
		this.connectionBank.addSlot(slot);
		return slot;
	},
    
    generateSQL: function () {
		var sSQL = 'CREATE TABLE `' + this.getName() + '` (<br />';
		var sFieldsSQL = '';
		for (var i = 0; i < this.fieldsSet.getFields().length; i++) {
			sFieldsSQL += (sFieldsSQL != '' ? ',<br />' : '') + this.fieldsSet.getFields()[i].generateSQL();
		}
		sSQL += sFieldsSQL + ') ENGINE=' + MYSQL_ENGINES[this.getEngine()] + ';';
		return sSQL;
    },
	collapse: function () {
		this.fieldsSet.div.style.display = 'none';
		this.engine.div.style.display = 'none';
		this.height = this.div.clientHeight;
		this.div.style.height = this.bar.div.clientHeight;
	},
	expand: function () {
		this.fieldsSet.div.style.display = 'block';
		this.engine.div.style.display = 'block';
		this.div.style.height = this.height;
	},
	dispose: function () {
		for (var i = 0; i < MyEntity.prototype.entities.length; i++) {
			if (MyEntity.prototype.entities[i]!=null && MyEntity.prototype.entities[i].name == this.getName()) {
				MyEntity.prototype.entities[i] = null;
			}
		};
		MyEntity.prototype.counter -= 1;
		JTKWidget.prototype.dispose.call(this);
	}
});

var MySqlText = Class.create();
MySqlText.prototype = Object.extend(new JTKWindow(), {
	/*
	 * This is constructor of MySqlText;
	 * @constructor
	 * @base JTKWindow
	 */
	initialize: function () {
		var oThis = this;
        this.bar = new JTKDraggableBar('SQL');
		this.bar.setClass('MyDraggableBar');
		this.setClass('MySqlText');
		this.close = new JTKImg();
		this.close.setImage('img/close.gif');
		this.bar.show(this);
		this.close.show(this.bar);
		this.close.setOnClick(function () {
			oThis.dispose();
		});
		this.pane = new JTKWidget();
		this.pane.setClass('MySqlTextPane');
		this.pane.show(this);
        this.show($('pane'));
        this.setPosition(new JTKPoint(Math.round((document.body.clientWidth / 2) - (this.div.clientWidth / 2)), 20));
	},
	setText: function (sText) {
		this.pane.setInnerHTML(sText);
	},
	/*
	 * This is class destructor
	 */
	dispose: function () {
		JTKWidget.prototype.dispose.call(this);
	}
});